package conversion;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Reprezentuje uzytkownika. Udizela informacji o tym, w jakich sesjach ten
 * uzytkownik uczestniczyl. Identyfikacja uzytkownikow opiera sie o adresy IP.
 * 
 * @author Marcin
 * 
 */
public class User {
	private final String id;
	private final List<Session> sessions;

	protected User(String id, List<Request> requests, int sessionsSeparator) {
		this.id = id;
		this.sessions = separateSessions(requests, sessionsSeparator);
	}

	private List<Session> separateSessions(List<Request> requests,
		int sessionsSecSeparator) {
		// sortuj zadania po dacie
		ArrayList<Request> requestsCopy = new ArrayList<Request>(requests);
		System.out.println("sorting user's requests");
		Collections.sort(requestsCopy, new Comparator<Request>() {

			@Override
			public int compare(Request r1, Request r2) {
				return r1.getTime().compareTo(r2.getTime());
			}

		});
		System.out.println("splitting into sessions");
		List<Integer> separationsIndexes =
			separationsIndexes(requestsCopy, sessionsSecSeparator);
		return splitToSessions(requestsCopy, separationsIndexes,
			sessionsSecSeparator);
	}

	private List<Session> splitToSessions(ArrayList<Request> requestsCopy,
		List<Integer> separationsIndexes, int sessionsSecSeparator) {

		List<Session> result = new ArrayList<Session>();

		for (int i = 0; i < separationsIndexes.size() - 1; ++i) {
			result.add(new Session(this, requestsCopy.subList(
				separationsIndexes.get(i), separationsIndexes.get(i + 1)),
				sessionsSecSeparator));
		}
		return result;
	}

	private List<Integer> separationsIndexes(List<Request> sortedRequests,
		int sessionsSecSeparator) {
		List<Integer> result = new ArrayList<Integer>();
		result.add(0);
		for (int i = 0; i < sortedRequests.size() - 1; ++i) {
			Calendar r1time = sortedRequests.get(i).getTime();
			Calendar r2time = sortedRequests.get(i + 1).getTime();
			if (r2time.getTimeInMillis() - r1time.getTimeInMillis() > (long) sessionsSecSeparator * 1000) {
				result.add(i + 1);
			}
		}
		result.add(sortedRequests.size());
		return result;
	}

	public String getId() {
		return this.id;
	}

	public List<Session> getSessions() {
		return Collections.unmodifiableList(this.sessions);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return this.id;
	}

}
